﻿using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.Unity.Utility;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using ZRT.RHPX.Entity;

namespace ZRT.RHPX.Core.Ioc
{
    /// <summary>
    /// 使用Unity实现依赖注入
    /// </summary>
    public class UnityDependencyResolver : IDependencyResolver
    {
        static object syncObj = new object();
        static Dictionary<string, IUnityContainer> containers = new Dictionary<string, IUnityContainer>();
        public IUnityContainer UnityContainer { get; private set; }

        public UnityDependencyResolver(string containerName = "")
        {
            if (containers.ContainsKey(containerName))
            {
                this.UnityContainer = containers[containerName];
                return;
            }
            lock (syncObj)
            {
                if (containers.ContainsKey(containerName))
                {
                    this.UnityContainer = containers[containerName];
                    return;
                }
                IUnityContainer container = new UnityContainer();
                //配置UnityContainer
                UnityConfigurationSection configSection = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;
                if (null == configSection && !string.IsNullOrEmpty(containerName))
                {
                    throw new ConfigurationErrorsException("The <unity> configuration section does not exist.");
                }
                if (null != configSection)
                {
                    if (string.IsNullOrEmpty(containerName))
                    {
                        configSection.Configure(container);
                    }
                    else
                    {
                        configSection.Configure(container, containerName);
                    }
                }
                containers.Add(containerName, container);
                this.UnityContainer = containers[containerName];
            }
        }

        public object GetService(Type serviceType)
        {
            Guard.ArgumentNotNull(serviceType, "serviceType");
            return CanResolve(serviceType) ? UnityContainer.Resolve(serviceType) : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            Guard.ArgumentNotNull(serviceType, "serviceType");
            return UnityContainer.ResolveAll(serviceType) ?? Enumerable.Empty<object>();
        }

        /// <summary>
        /// 是否可以被恢复
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool CanResolve(Type type)
        {
            if (isResolvableClass(type))
                return true;
            return IsRegistered(type);
        }

        /// <summary>
        /// 是否是可以被恢复的类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool isResolvableClass(Type type)
        {
            return type.IsClass && !type.IsAbstract;
        }

        /// <summary>
        /// 是否已经注册
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool IsRegistered(Type type)
        {
            return UnityContainer.IsRegistered(type);
        }
    }
}
